package com.atguigu.gulimall.search.thread;

import java.util.concurrent.*;

public class ThreadTest {
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main.....start.....");
//        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//        }, executor);

        /**
         * 方法完成后的感知
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 /0;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).whenComplete((res, exception)->{
//            //虽然能得到异常信息，但是没法修改返回数据
//            System.out.println("异步任务完成了...结果是："+res+"异常是："+exception);
//        }).exceptionally(throwable -> {
//            //可以感知异常，同时返回默认值
//            return 10;
//        });

        /**
         * 方法执行完后的处理
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).handle((res, thr) -> {
//            if(res != null) {
//                return res * 2;
//            }
//            if(thr != null) {
//                return 0;
//            }
//            return 0;
//        });

//        CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).thenRunAsync(()->{
//            System.out.println("任务2启动了");
//        },executor);

//        CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).thenAcceptAsync(res -> {
//            System.out.println("任务2启动了..."+ res);
//        }, executor);

//        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).thenApplyAsync(res -> {
//            System.out.println("任务2启动了..." + res);
//            return "hello " + res;
//        }, executor);

        CompletableFuture<Object> futurep01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1开始：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束：");
            return i;
        }, executor);


        CompletableFuture<Object> futurep02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2开始：" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
                System.out.println("任务2结束：");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            return "Hello";
        }, executor);

//        futurep01.runAfterBothAsync(futurep02, () -> {
//            System.out.println("任务3开始");
//        },executor);

//        futurep01.thenAcceptBothAsync(futurep02, (f1, f2)->{
//            System.out.println("任务3开始...前两个线程的结果："+ f1 + "---->>>" + f2);
//        }, executor);

//        CompletableFuture<String> future = futurep01.thenCombineAsync(futurep02, (f1, f2) -> {
//            return f1 +":"+ f2 + "-->haha";
//        }, executor);

//        futurep01.runAfterEitherAsync(futurep02,()->{
//            System.out.println("任务3开始");
//        },executor);

//        futurep01.acceptEitherAsync(futurep02, (res) -> {
//            System.out.println("任务3开始...之前的结果："+res);
//        }, executor);

        CompletableFuture<Object> future = futurep01.applyToEitherAsync(futurep02, (res) -> {
            System.out.println("任务3开始...之前的结果："+res);
            return res.toString() + ",.,.,.,.";
        }, executor);

        System.out.println("main.....end....." + future.get());
    }

    public void thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main.....start.....");
        /**
         *  1）、继承Thread
         *  Thread01 thread01 = new Thread01();
         *         thread01.start();
         *  2）、实现Runnable 接口
         *  Runnable02 runnable02 = new Runnable02();
         *         Thread thread = new Thread(runnable02);
         *         thread.start();
         *  3）、实现Callable 接口+ FutureTask （可以拿到返回结果，可以处理异常）
         *  阻塞等待整个线程执行完成，获取返回结果
         *  FutureTask<Integer> futureTask = new FutureTask<>(new Callable03());
         *         new Thread(futureTask).start();
         *         Integer i = futureTask.get();
         *  4）、线程池
         *  给线程池直接提交任务
         */

        //当前系统中池只有一两个，每个异步任务提交给线程池他自己去执行
        executor.execute(new Runnable02());
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        /**
         * 常用的线程池
         */
        //Executors.newCachedThreadPool(); core是0，所有都可回收
//        Executors.newFixedThreadPool(); 固定大小，core=max，都不可回收
//        Executors.newSingleThreadExecutor(); 支持定时及周期性任务执行
//        Executors.newSingleThreadExecutor();创建一个单线程化的线程池，它只会用唯一的工作线程来执行任务，保证所有任务
//按照指定顺序(FIFO, LIFO, 优先级)执行。

        System.out.println("main.....end.....");
    }

    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }

    public static class Runnable02 implements Runnable {

        @Override
        public void run() {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }

    public static class Callable03 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }
    }
}
